'''
基于epoll 的 IO多路复用并发模型
重点代码

目标:服务端能够同时应对多个客户端发消息和连接
思路:将监听套接字与连接套接字一起监控
'''
from socket import *
from select import *

HOST = '0.0.0.0'
PORT = 1211
ADDR = (HOST, PORT)
map = {}


# 处理客户端连接
def connect_client(ep, sock):
    connfd, addr = sock.accept()
    print('Connect from', addr)
    connfd.setblocking(False)
    ep.register(connfd, EPOLLIN)
    map[connfd.fileno()] = connfd


# 客户端发送连接
def handle(ep, key):
    data = map[key].recv(1024)
    if not data:
        del map[key]  # 从监控列表删除
        ep.unregister(map[key], EPOLLIN)
        map[key].close()
        return  # 继续处理下一个IO
    print(data.decode())
    map[key].send(b'ok')


# 启动服务函数
def main():
    # 创建监听套接字
    sock = socket()
    sock.bind(ADDR)
    sock.listen(5)
    sock.setblocking(False)
    print('Listen the port %d' % PORT)

    ep = epoll()
    ep.register(sock, EPOLLIN)
    map[sock.fileno()] = sock
    # 循环接受监控IO发生
    while True:
        events = ep.poll()
        print('123')
        for key, value in events:
            if key == sock.fileno():
                connect_client(ep, map[key])
            else:
                handle(ep, key)


if __name__ == '__main__':
    main()
